#include "bsp_usart.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_rcc.h"
#include "misc.h"
#include "stm32f10x.h"
#include "stdio.h"

#define USART_DEBUG_TYPE    (USART1)   
#define USART_DEBUG_TX_PORT (GPIOA)
#define USART_DEBUG_TX_PIN  (GPIO_Pin_9)

#define USART_DEBUG_RX_PORT (GPIOA)
#define USART_DEBUG_RX_PIN  (GPIO_Pin_10)


#define EN_USART1_RX        (1)

/**********************************************************************************
  * @brief  usart1 initial function
  * @param  baud
  * @note  
  * @retval None
  *********************************************************************************
*/
void bsp_usart_1_init(uint32_t baud)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* 1. 串口时钟使能，GPIO 时钟使能，复用时钟使能 */
    //使能 USART1,GPIOA 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    /* 2. 串口复位 */
    USART_DeInit(USART_DEBUG_TYPE);
    /* 3. GPIO 端口模式设置*/
    // Usart1_TX
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     // 复用推挽输出
    GPIO_Init(USART_DEBUG_TX_PORT, &GPIO_InitStructure);
    // Usart1_RX
    GPIO_InitStructure.GPIO_Pin = USART_DEBUG_RX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //浮空输入
    GPIO_Init(USART_DEBUG_RX_PORT, &GPIO_InitStructure);
    /* 4. 串口参数初始化 */
    USART_InitStructure.USART_BaudRate = baud;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
    USART_Init(USART_DEBUG_TYPE, &USART_InitStructure);
    #if EN_USART1_RX //如果使能了接收
    /* 5. 初始化 NVIC */
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级 3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
        NVIC_Init(&NVIC_InitStructure); //中断优先级初始化
        /* 开启中断*/
        USART_ITConfig(USART_DEBUG_TYPE, USART_IT_RXNE, ENABLE);    //开启中断
        // USART_ITConfig(USART_DEBUG_TYPE, USART_IT_TC, ENABLE);      //开启中断
    #endif
    /* 6. 使能串口 */
    USART_Cmd(USART_DEBUG_TYPE, ENABLE);
}

/**********************************************************************************
  * @brief  send one uint16_t data via usart. 
  * @param  e_usart_type, us_tx_data
  * @note  需要根据不同的芯片来改变它
  * @retval None
  *********************************************************************************
*/
void bsp_usart_send_data(usart_type_Enum e_usart_type, uint16_t us_tx_data)
{
    switch(e_usart_type)
    {
        case usart0_enum:
            break;
        case usart1_enum:
            USART_SendData(USART1, us_tx_data);
            break;
        case usart2_enum:
            USART_SendData(USART2, us_tx_data);
            break;
        case usart3_enum:
            USART_SendData(USART3, us_tx_data);
            break;
        case usart4_enum:
            USART_SendData(UART4, us_tx_data);
            break;
        default:
            break;
    }
}
// /**********************************************************************************
//   * @brief  接收 
//   * @param  e_usart_type: 抽象出来的usart类型
//   * @note  需要根据不同的芯片来改变它
//   * @retval None
//   *********************************************************************************
// */
// uint16_t bsp_usart_receive_data(usart_type_Enum e_usart_type)
// {
//     uint16_t retVal = 0;
//     switch(e_usart_type)
//     {
//         case usart0_enum:
//             break;
//         case usart1_enum:
//             retVal = USART_ReceiveData(USART1);
//             break;
//         case usart2_enum:
//             retVal = USART_ReceiveData(USART2);
//             break;
//         case usart3_enum:
//             retVal = USART_ReceiveData(USART3);
//             break;
//         case usart4_enum:
//             retVal = USART_ReceiveData(UART4);
//             break;
//         default:
//             break;
//     }
//     return retVal;
// }

//加入以下代码,支持 printf 函数,而不需要选择 use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数 
struct __FILE 
{ 
    int handle;
}; 
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式 
_sys_exit(int x) 
{ 
    x = x; 
}
//重定义 fputc 函数
int fputc(int ch, FILE *f)
{ 
    while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); 
    USART_SendData(USART1,(uint8_t)ch); 
    return ch;
}

#endif
